/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
*/

package com.jinhe.tss.core.cachepool.proxy;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.jinhe.tss.core.cachepool.AbstractCacheableKey;
import com.jinhe.tss.core.cachepool.Cacheable;
import com.jinhe.tss.core.cachepool.CacheableKey;
import com.jinhe.tss.core.cachepool.DefaultCacheableKey;
import com.jinhe.tss.core.util.BeanUtil;


/** 
 * <p> ProxyContainer.java </p> 
 * <p>
 * 对缓存池容器进行动态代理封装，使得容器执行put，get，remove等方法时， <br>
 * key 值如果为String或其它非CacheableKey类型，则自动转换为DefaultCacheableKey。<br>
 * 
 * 如果调用的是put方法，则取缓存项的name属性，不为空的话，设置到CacheableKey的getName()中。<br>
 * </p>
 * 
 * @author Jon.King 2007-1-9
 */
public class ProxyContainer {
    
    public static Object wrap(Object object) {
        
        Class<?>[] interfaces = ProxyUtil.getInterfaces(object.getClass()); 
        
        String[] invokeMethods = new String[]{"put", "get", "remove"};
        
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                interfaces, new BaseInvocationHandler(object, invokeMethods) {
            
            //参考父类，执行invokeMethods包含的方法时，before方法将被触发
            protected Object before(Object target, Method method, Object[] args){
                if(!(args[0] instanceof CacheableKey)) {
                    args[0] = new DefaultCacheableKey(args[0].toString());
                }
                
                //特殊处理put方法，将value中的name属性值取出作为key的name。
                if(method.getName().equals("put")){
                    final CacheableKey key = (CacheableKey) args[0];
                    final String name = getCacheItemName((Cacheable) args[1]);
                    args[0] = new AbstractCacheableKey(){
                        private static final long serialVersionUID = 213500451687728342L;
                        public String getKey() {
                            return key.getKey();
                        }
                        public String getName() {
                            return name;
                        }
                        public String getRemark() {
                            return key.getRemark();
                        }
                    };
                }
                return null;
            }
            
            protected void after(Object target, Method method, Object[] args, Object beforeReturnVal){
            }
            
            private String getCacheItemName(Cacheable item){
                try{
                    return BeanUtil.getPropertyValue(item.getValue(), "name").toString();
                }catch(Exception e){
                    return null;
                }
            }
        });
    }
}